package com.tuanzi.loan.web.domain;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.primefaces.model.menu.*;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tuanzi.loan.business.entity.system.Menu;
import com.tuanzi.loan.business.service.system.MenuService;
import com.tuanzi.loan.core.util.SpringContextHolder;

/**
 * @author Ray 2017/09/21
 */
public class MenuDomain {

	private MenuService menuService = SpringContextHolder.getBean(MenuService.class);

	public TreeNode generateTreeNode() {
		TreeNode treeNode = new DefaultTreeNode("Root", null);
		treeNode.setExpanded(true);
		TreeNode root = structureTreeRoot();
		treeNode.getChildren().add(root);

		final List<Menu> topMenuMap = Lists.newArrayList();
		final Map<String/* parentId */, List<Menu>> subMenuMap = Maps.newHashMap();
		for (Menu menu : menuService.findAll()) {

			if (menu.getParentId() == null) {
				topMenuMap.add(menu);
			} else {
				List<Menu> menus = subMenuMap.get(menu.getParentId());
				if (menus == null) {
					menus = Lists.newArrayList();
				}
				menus.add(menu);
				subMenuMap.put(menu.getParentId(), menus);
			}
		}

		topMenuMap.stream().sorted(Comparator.comparing(Menu::getSort)).map(x -> this.generateTreeNode(x, subMenuMap)).forEach(x -> root.getChildren().add(x));
		return treeNode;
	}

	private TreeNode generateTreeNode(Menu menu, Map<String/* parentId */, List<Menu>> subMenuMap) {
		if (menu.getLeaf() || CollectionUtils.isEmpty(subMenuMap.get(menu.getId()))) {
			return createTreeNode(menu);
		}
		TreeNode branchTreeNode = createTreeNode(menu);
		branchTreeNode.getChildren().addAll(
				subMenuMap.get(menu.getId()).stream().sorted(Comparator.comparing(Menu::getSort)).map(x -> this.generateTreeNode(x, subMenuMap)).collect(Collectors.toList()));

		return branchTreeNode;
	}

	private TreeNode createTreeNode(Object data) {
		TreeNode treeNode = new DefaultTreeNode(data);
		return treeNode;
	}

	private TreeNode createTreeRootNode(Object data) {
		TreeNode treeNode = new DefaultTreeNode(data);
		treeNode.setExpanded(true);
		return treeNode;
	}

	private TreeNode structureTreeRoot() {
		Menu root = new Menu();
		root.setTitle("菠萝天眼");
		root.setIcon("fa fa-yen");
		root.setEnable(true);
		root.setLeaf(false);
		return createTreeRootNode(root);
	}

	public MenuModel generateMenuModel(List<Menu> menus) {
		MenuModel menuModel = new DefaultMenuModel();

		final List<Menu> topMenuMap = Lists.newArrayList();
		final Map<String/* parentId */, List<Menu>> subMenuMap = Maps.newHashMap();
		for (Menu menu : menus) {

			if (menu.getParentId() == null) {
				topMenuMap.add(menu);
			} else {
				addMenu(subMenuMap, menu);
			}
		}

		topMenuMap.stream().sorted(Comparator.comparing(Menu::getSort)).map(x -> structureMenuElement(x, subMenuMap)).forEach(menuModel::addElement);

		return menuModel;
	}

	@SuppressWarnings("unchecked")
	private MenuElement structureMenuElement(Menu menu, Map<String/* parentId */, List<Menu>> subMenuMap) {

		if (menu.getLeaf() || CollectionUtils.isEmpty(subMenuMap.get(menu.getId()))) {
			return structureMenuItem(menu);
		}

		Submenu subMenu = structureSubmenu(menu);
		subMenu.getElements().addAll(
				subMenuMap.get(menu.getId()).stream().sorted(Comparator.comparing(Menu::getSort)).map(x -> structureMenuElement(x, subMenuMap)).collect(Collectors.toList()));

		return subMenu;
	}

	private void addMenu(Map<String, List<Menu>> menuMap, Menu menu) {
		List<Menu> menus = menuMap.get(menu.getParentId());
		if (menus == null) {
			menus = Lists.newArrayList();
		}
		menus.add(menu);
		menuMap.put(menu.getParentId(), menus);
	}

	private MenuItem structureMenuItem(Menu menu) {
		DefaultMenuItem menuItem = new DefaultMenuItem();
		menuItem.setUrl(menu.getUrl());
		menuItem.setValue(menu.getTitle());
		menuItem.setIcon(menu.getIcon());
		return menuItem;
	}

	private Submenu structureSubmenu(Menu menu) {
		DefaultSubMenu subMenu = new DefaultSubMenu();
		subMenu.setLabel(menu.getTitle());
		subMenu.setIcon(menu.getIcon());
		return subMenu;
	}

}
